/*
 *所有关于Ads_AbnormalType类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*Ads_AbnormalTypeService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using DGZImp.AdsProject.DomainModels;
using DGZImp.Core.Utilities;
using DGZImp.Core.Extensions;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using DGZImp.AdsProject.IRepositories;
using DGZImp.Core.DbSqlSugar;
using SqlSugar;
using DGZImp.Core.Exceptions;
using System.Configuration;
using Microsoft.Extensions.Configuration;
using DGZImp.Core.EFDbContext;
using DGZImp.Core.ManageUser;
using AutoMapper;
using Newtonsoft.Json;
using System.Collections.Generic;

namespace DGZImp.AdsProject.Services
{
    public partial class Ads_AbnormalTypeService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IAds_AbnormalTypeRepository _repository;//访问数据库
        public ISqlSugarClient SysDb = AutofacContainerModule.GetService<SysDbContext>()?.SqlSugarClient;
        WebResponseContent webResponse = new WebResponseContent();
        private readonly IMapper _mapper;

        [ActivatorUtilitiesConstructor]
        public Ads_AbnormalTypeService(
            IAds_AbnormalTypeRepository dbRepository,
            IHttpContextAccessor httpContextAccessor,
            IMapper mapper
            )
        : base(dbRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            _repository = dbRepository;
            _mapper = mapper;
            //多租户会用到这init代码，其他情况可以不用
            //base.Init(dbRepository);
        }

        public override WebResponseContent Add(SaveModel saveDataModel)
        {
            // 在保存数据库前的操作，所有数据都验证通过了，这一步执行完就执行数据库保存
            AddOnExecuting = (Ads_AbnormalType order, object list) =>
            {
                if (order.ParentId.HasValue)
                {
                    //判断上级节点是否存在
                    var nodeExist = _repository.Exists(x => x.AbnormalTypeId == order.ParentId && x.IsValid == 1);
                    if (!nodeExist) return webResponse.Error($"不存在该父级节点({order.ParentId})");
                }

                var exist = _repository.Exists(x => x.AbnormalCode == order.AbnormalCode && x.IsValid == 1);
                if (exist) return webResponse.Error("已经存在相同的异常类型");

                return webResponse.OK();
            };

            return base.Add(saveDataModel);
        }

        public override WebResponseContent Update(SaveModel saveDataModel)
        {
            // 在保存数据库前的操作，所有数据都验证通过了，这一步执行完就执行数据库保存
            UpdateOnExecuting = (Ads_AbnormalType order, object addList, object updateList, List<object> delKeys) =>
            {
                if (order.ParentId.HasValue)
                {
                    //判断上级节点是否存在
                    var nodeExist = _repository.Exists(x => x.AbnormalTypeId == order.ParentId && x.IsValid == 1);
                    if (!nodeExist) return webResponse.Error($"不存在该父级节点({order.ParentId})");
                }

                var exist = _repository.Exists(x => x.AbnormalCode == order.AbnormalCode && x.IsValid == 1);
                if (exist) return webResponse.Error("已经存在相同的异常类型");

                return webResponse.OK();
            };

            return base.Update(saveDataModel);
        }

        public override WebResponseContent Del(object[] keys, bool delList = true)
        {
            //var ids = keys.Select(s => s.GetGuid()).ToList();
            //如果主键是int类型，用GetInt转换
            var ids = keys.Select(s => s.GetLong()).ToList();
            var delIds = new List<long>();
            //查询数据库中是否有些数据
            var datas = repository.FindAsIQueryable(x => ids.Contains(x.AbnormalTypeId)
                    && x.IsValid == 1).Select(s => s.AbnormalTypeId).ToList();
            //递归查询子节点
            foreach (var id in datas)
            {
                delIds.Add(id);
                delIds.AddRange(GetChildIds(id));
            }
            //判断这些节点是否被异常任务引用
            var taskExist = repository.DbContext.Queryable<Ads_Task>().Any(t =>delIds.Contains(t.AbnormalTypeId));
            if (taskExist) return webResponse.Error("异常类型已被异常任务引用，不可删除！");

            //删除这些子节点和超时提醒列表
            repository.DbContext.Deleteable<Ads_TimeoutAlert>().Where(t => t.IsValid == 1
            && delIds.Contains(t.AbnormalTypeId)).ExecuteCommand();
            repository.DbContext.Deleteable<Ads_AbnormalType>().Where(t => t.IsValid == 1
            && delIds.Contains(t.AbnormalTypeId)).ExecuteCommand();

            return base.Del(keys, delList);
        }

        /// <summary>
        /// 获取某一节点下的所有子节点ID
        /// </summary>
        /// <param name="parentId"></param>
        /// <returns></returns>
        private List<long> GetChildIds(long parentId)
        {
            var childIds = new List<long>();

            // 查询直接子节点
            var children = repository.DbContext.Set<Ads_AbnormalType>().Where(t => t.ParentId == parentId).ToList();
            foreach (var child in children)
            {
                childIds.Add(child.AbnormalTypeId); // 添加当前子节点ID
                childIds.AddRange(GetChildIds(child.AbnormalTypeId)); // 递归获取子节点的子节点
            }

            return childIds;
        }

        /// <summary>
        /// 分页获取树状结构的异常类型
        /// </summary>
        /// <param name="inDto"></param>
        /// <returns></returns>
        public async Task<List<AbnormalTypeDto>> GetTree(bool isFilter)
        {
            List<AbnormalTypeDto> result = new List<AbnormalTypeDto>();
            var user = UserContext.Current.UserName;

            var items = Db.Queryable<Ads_AbnormalType>()
                .Where(x => x.IsValid == 1 && x.ParentId == null)
                .OrderBy(x => x.AbnormalTypeId).ToList();

            // 递归查询子节点
            foreach (var item in items)
            {
                AbnormalTypeDto abnormalTypeDto = new AbnormalTypeDto();
                abnormalTypeDto = _mapper.Map<AbnormalTypeDto>(item);
                abnormalTypeDto.Children = await GetChildrenAsync(Db, item.AbnormalTypeId);
                if (isFilter)
                {
                    if (string.IsNullOrEmpty(item.Depts))
                    {
                        result.Add(abnormalTypeDto);
                    }
                    else
                    {
                        //string转json格式
                        var depts = JsonConvert.DeserializeObject<List<List<long>>>(item.Depts);
                        if (depts==null||depts.Count()==0)
                        {
                            result.Add(abnormalTypeDto);
                        }
                        else
                        {
                            foreach (var dept in depts)
                            {
                                //取dept的最后一个值
                                var subDept = dept.Last();
                                //判断用户是否在部门中
                                var userDept = UserContext.Current.DeptIds;
                                if (userDept.Contains(subDept))
                                {
                                    result.Add(abnormalTypeDto);
                                    break;
                                }
                            }
                        }
                    }
                }
                else
                {
                    result.Add(abnormalTypeDto);
                }
            }

            return result;
        }

        /// <summary>
        /// 递归查询后续子节点
        /// </summary>
        /// <param name="context"></param>
        /// <param name="parentId"></param>
        /// <returns></returns>
        private async Task<List<AbnormalTypeDto>> GetChildrenAsync(ISqlSugarClient context, long parentId)
        {
            var children = await context.Set<Ads_AbnormalType>()
                .Where(x => x.ParentId == parentId)
                .Select(x => new AbnormalTypeDto
                {
                    AbnormalTypeId = x.AbnormalTypeId,
                    AbnormalCode = x.AbnormalCode,
                    AbnormalName = x.AbnormalName,
                    ParentId = parentId
                })
                .ToListAsync();

            // 递归查询子节点的子节点
            foreach (var child in children)
            {
                child.Children = await GetChildrenAsync(context, child.AbnormalTypeId);
            }

            return children;
        }

        /// <summary>
        /// 获取异常类型详情
        /// </summary>
        /// <param name="AbnormalTypeId"></param>
        /// <returns></returns>
        public async Task<AbnormalTypeDetailDto> GetDetail(long AbnormalTypeId)
        {
            AbnormalTypeDetailDto result = new AbnormalTypeDetailDto();
            //获取异常类型的基本信息
            var type = await Db.Set<Ads_AbnormalType>().Where(x => x.IsValid == 1
                && x.AbnormalTypeId == AbnormalTypeId).FirstOrDefaultAsync();

            if (type == null)
            {
                throw new AppException($"未查询到该节点信息，请核对数据（id:{AbnormalTypeId}）！");
            }

            result = _mapper.Map<AbnormalTypeDetailDto>(type);

            //获取异常类型的超时提醒信息
            result.TimeoutAlerts = await Db.Set<Ads_TimeoutAlert>().Where(x => x.IsValid == 1
                && x.AbnormalTypeId == AbnormalTypeId)
                .Select(x => new TimeoutAlertDto
                {
                    AbnormalTypeId = x.AbnormalTypeId,
                    Post = x.Post,
                    TimeoutAlertMinutes = x.TimeoutAlertMinutes
                }).ToListAsync();

            return result;
        }

        /// <summary>
        /// 添加或更新异常类型
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        /// <exception cref="AppException"></exception>
        public async Task<long> AddOrUpdate(AbnormalTypeDetailDto dto)
        {
            long id=0;

            #region 检查入参
            if(string.IsNullOrWhiteSpace(dto.AbnormalName)) throw new AppException($"异常名称不可为空！");
            if (string.IsNullOrWhiteSpace(dto.AbnormalCode)) throw new AppException($"异常编码不可为空！");

            if(string.IsNullOrWhiteSpace(dto.ResponsiblePersons) && string.IsNullOrWhiteSpace(dto.ResponsiblePersons))
                throw new AppException($"负责部门和负责人不可同时为空！");

            if (dto.TimeoutAlerts.Count() == 1)
            {
                if (string.IsNullOrWhiteSpace(dto.TimeoutAlerts[0].Post))
                {
                    dto.TimeoutAlerts = new List<TimeoutAlertDto>();
                }
                else
                {
                    if (dto.TimeoutAlerts[0].TimeoutAlertMinutes <= 0)
                    {
                        throw new AppException($"超时提示时间需要大于0！");
                    }
                }
            }
            else
            {
                foreach (var item in dto.TimeoutAlerts)
                {
                    if (string.IsNullOrWhiteSpace(item.Post)) throw new AppException($"超时提醒的岗位为空！");
                    if (item.TimeoutAlertMinutes <= 0) throw new AppException($"超时提示时间需要大于0！");
                }
            }

            #endregion

            bool inTrans = _repository.SqlSugarClient.Ado.Transaction != null;
            if (!inTrans) _repository.SqlSugarClient.Ado.BeginTran();
            try
            {
                if (dto.AbnormalTypeId > 0)
                {
                    id = dto.AbnormalTypeId;
                    
                    await _repository.DbContext.Updateable<Ads_AbnormalType>()
                        .SetColumns(a => a.AbnormalCode == dto.AbnormalCode)
                        .SetColumns(a => a.AbnormalName == dto.AbnormalName)
                        .SetColumns(a => a.Depts == dto.Depts)
                        .SetColumns(a => a.Priority == dto.Priority)
                        .SetColumns(a => a.ResponsibleDept == dto.ResponsibleDept)
                        .SetColumns(a => a.ResponsiblePersons == dto.ResponsiblePersons)
                    .Where(a => a.AbnormalTypeId == dto.AbnormalTypeId).ExecuteCommandAsync();

                    //更新超时提醒
                    await _repository.DbContext.Deleteable<Ads_TimeoutAlert>().Where(t => t.AbnormalTypeId == dto.AbnormalTypeId).ExecuteCommandAsync();
                    foreach (var item in dto.TimeoutAlerts)
                    {
                        if (string.IsNullOrEmpty(item.Post))
                        {
                            continue;
                        }
                        _repository.DbContext.DoInsert(new Ads_TimeoutAlert
                        {
                            AbnormalTypeId = dto.AbnormalTypeId,
                            Post = item.Post,
                            TimeoutAlertMinutes = item.TimeoutAlertMinutes
                        });
                    }
                }
                else
                {
                    //新增异常类型
                    id = await _repository.DbContext.DoInsertAsync(new Ads_AbnormalType
                    {
                        AbnormalCode = dto.AbnormalCode,
                        AbnormalName = dto.AbnormalName,
                        Depts = dto.Depts,
                        Priority = dto.Priority,
                        ResponsibleDept = dto.ResponsibleDept,
                        ResponsiblePersons = dto.ResponsiblePersons,
                        ParentId = dto.ParentId
                    });
                    //新增超时提醒
                    foreach (var item in dto.TimeoutAlerts)
                    {
                        if (string.IsNullOrEmpty(item.Post))
                        {
                            continue;
                        }
                        await _repository.DbContext.DoInsertAsync(new Ads_TimeoutAlert
                        {
                            AbnormalTypeId = id,
                            Post = item.Post,
                            TimeoutAlertMinutes = item.TimeoutAlertMinutes
                        });
                    }
                }

                if (!inTrans) await _repository.SqlSugarClient.Ado.CommitTranAsync();
                return id;
            }
            catch (Exception e)
            {
                if (!inTrans) _repository.SqlSugarClient.Ado.RollbackTran();
                throw new AppException("保存失败！详情：" + e.Message);
            }
        }

        /// <summary>
        /// 通过部门获取用户
        /// </summary>
        /// <param name="deptId"></param>
        /// <returns></returns>
        public async Task<List<keyValueDto>> GetUsersByDept(long deptId)
        {
            var deptIdString = deptId.ToString();
            var users = await SysDb.Queryable<Sys_User>().Where(x => x.IsValid == 1
                && x.DeptIds.Contains(deptIdString)).Select(t => new keyValueDto
                {
                    key = t.UserName,
                    value = t.UserTrueName
                }).ToListAsync();
            return users;
        }
    }
}
